package com.tencent.cloud.iov.kernel.service;

import android.text.TextUtils;

import com.tencent.cloud.iov.kernel.BuildConfig;
import com.tencent.cloud.iov.kernel.service.interceptor.CookieInterceptor;
import com.tencent.cloud.iov.kernel.service.interceptor.StatisticsInterceptor;
import com.tencent.cloud.iov.kernel.service.interceptor.StatusInterceptor;
import com.tencent.cloud.iov.util.backdoor.authority.SwitchAuthorityInterceptor;
import com.tencent.mars.xlog.Log;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * HTTP 服务创建类
 * <p>
 * OkHttpClient 使用同一对象，作为统一网络请求出口
 * Retrofit 可根据不同服务器请求，创建多个对象（实际网络请求都由统一的 OkHttpClient 执行）
 *
 * @author showxiao
 * @date 2018/4/25
 */

public class ServiceGenerator {

    private static final long CONNECT_TIMEOUT = 10_000L;
    private static final long READ_TIMEOUT = 10_000L;
    private static final long WRITE_TIMEOUT = 10_000L;

    private static final String TAG_OK_HTTP = "OkHttp";
    private static final String LINE_SEPARATOR = System.getProperty("line.separator");
    private static final int INDENT_SPACES = 4;

    private static OkHttpClient sOkHttpClient;
    private static Map<String, Retrofit> sUrlRetrofitMap;

    /**
     * 创建服务
     *
     * @param serviceClass 请求 API 定义接口类
     * @param baseUrl      服务器地址
     * @param <T>
     * @return
     */
    public static <T> T createService(Class<T> serviceClass, String baseUrl) {
        return getRetrofit(baseUrl).create(serviceClass);
    }

    /**
     * 获取 retrofit 对象
     * <p>
     * 根据不同服务器地址创建对应的 Retrofit 对象
     *
     * @param baseUrl
     * @return
     */
    public static Retrofit getRetrofit(String baseUrl) {
        if (sUrlRetrofitMap == null) {
            sUrlRetrofitMap = new HashMap<>();
        }

        if (sUrlRetrofitMap.containsKey(baseUrl)) {
            return sUrlRetrofitMap.get(baseUrl);
        }

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(GsonConverterFactory.create())
                .client(getOkHttpClient())
                .build();
        sUrlRetrofitMap.put(baseUrl, retrofit);

        return retrofit;
    }

    /**
     * OkHttp 请求客户端
     *
     * @return
     */
    public static OkHttpClient getOkHttpClient() {
        if (sOkHttpClient == null) {
            sOkHttpClient = new OkHttpClient.Builder()
                    .connectTimeout(CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)
                    .readTimeout(READ_TIMEOUT, TimeUnit.MILLISECONDS)
                    .writeTimeout(WRITE_TIMEOUT, TimeUnit.MILLISECONDS)
                    .addInterceptor(new StatisticsInterceptor())
                    .addInterceptor(new StatusInterceptor())
                    .addInterceptor(new CookieInterceptor())
                    .addInterceptor(new SwitchAuthorityInterceptor())
                    .addNetworkInterceptor(createHttpLoggingInterceptor())
                    .build();
        }

        return sOkHttpClient;
    }

    /**
     * Http 请求日志打印
     *
     * @return
     */
    private static Interceptor createHttpLoggingInterceptor() {
        return new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
                    @Override
                    public void log(String message) {
                        // 格式化 JSON 字符地串
                        String str = getJsonString(message);
                        if (!TextUtils.isEmpty(str)) {
                            String[] strArray = str.split(LINE_SEPARATOR);
                            for (String s : strArray) {
                                // 使用 XLog 进行日志打印
                                Log.i(TAG_OK_HTTP, s);
                            }
                        }
                    }
                })
                // TODO: 2018/10/16 @showxiao 正式发布版本，可以删除网络日志的打印和存储
                .setLevel(BuildConfig.DEBUG
                        ? HttpLoggingInterceptor.Level.BODY
                        : HttpLoggingInterceptor.Level.BODY/*NONE*/);
    }

    /**
     * 格式化 JSON 字符串
     *
     * @param msg
     * @return
     */
    private static String getJsonString(String msg) {
        String message;
        try {
            if (msg.startsWith("{")) {
                JSONObject jsonObject = new JSONObject(msg);
                message = jsonObject.toString(INDENT_SPACES);
            } else if (msg.startsWith("[")) {
                JSONArray jsonArray = new JSONArray(msg);
                message = jsonArray.toString(INDENT_SPACES);
            } else {
                message = msg;
            }
        } catch (JSONException var3) {
            message = msg;
        }

        return message;
    }

}
